<template>
    <div class="tnxbsv-upload">
        <BOverlay :show="uploading" spinner-variant="primary" spinner-small>
            <BInputGroup>
                <BFormInput :value="file?.name" :placeholder="placeholder" tabindex="-1" readonly/>
                <template #append>
                    <div class="input-group-append">
                        <i class="bi bi-x-circle icon-clear" @click="clear" v-if="empty"/>
                        <BButton :variant="buttonType" @click="toSelect">{{ buttonText }}</BButton>
                    </div>
                </template>
            </BInputGroup>
            <BFormFile class="d-none" v-model="file" :accept="uploadOptions.extensions || accept"/>
        </BOverlay>
        <div class="tnxbsv-upload-error" v-if="errorMessage">{{ errorMessage }}</div>
    </div>
</template>

<script>
import {BOverlay, BInputGroup, BFormInput, BButton, BFormFile} from 'bootstrap-vue-next';

export default {
    name: 'TnxbsvUpload',
    components: {BOverlay, BInputGroup, BFormInput, BButton, BFormFile,},
    props: {
        app: String, // 上传目标应用名称
        action: {
            type: String,
            required: true,
        },
        accept: [String, Array],
        uploadOptions: {
            type: Object,
            default: () => ({}),
        },
        placeholder: String,
        buttonType: {
            type: String,
            default: 'light',
        },
        buttonText: {
            type: String,
            default: '选择文件',
        },
        empty: Boolean,
        beforeUpload: Function,
        onSuccess: Function,
        onError: Function,
    },
    data() {
        return {
            file: null,
            uploading: false,
            errorMessage: null,
        };
    },
    computed: {
        actionUrl() {
            let baseUrl;
            if (this.app) {
                baseUrl = window.tnx.app.rpc.getBaseUrl(this.app);
            }
            baseUrl = baseUrl || window.tnx.app.rpc.getDefaultBaseUrl();
            return baseUrl + this.action;
        },
    },
    watch: {
        file(newFile, oldFile) {
            if (newFile) {
                if (!newFile.handled) {
                    this.uploadFile();
                }
            } else if (!oldFile.handled) {
                oldFile.handled = true;
                this.file = oldFile;
            }
        }
    },
    mounted() {
        this.file = null;
        this.uploading = false;
        this.errorMessage = null;
    },
    methods: {
        toSelect() {
            const $ = window.tnx.libs.$;
            $('.tnxbsv-upload input[type="file"]').trigger('click')
        },
        clear() {
            this.file.handled = true;
            this.$nextTick(() => {
                this.file = null;
            });
        },
        uploadFile() {
            if (this.file) {
                if (this.beforeUpload && this.beforeUpload(this.file) === false) {
                    return;
                }
                const formData = new FormData();
                formData.append('file', this.file);
                this.uploading = true;
                this.errorMessage = null;

                window.tnx.app.rpc.request(this.actionUrl, {
                    method: 'POST',
                    body: formData,
                    timeout: 0,  // 文件上传不设置超时
                    app: this.app,  // 指定目标应用
                    success: result => {
                        if (this.onSuccess) {
                            this.onSuccess(result);
                        } else {
                            console.log('文件上传成功:', result);
                        }
                        this.uploading = false;
                    },
                    error: error => {
                        this.uploading = false;
                        if (this.onError && this.onError(error) === false) {
                            return;
                        }
                        this.errorMessage = error.message;
                    }
                });
            }
        }
    }
}
</script>

<style>
.tnxbsv-upload input:focus {
    outline: none;
    box-shadow: none;
    border-color: var(--bs-border-color);
}

.tnxbsv-upload .input-group-append {
    position: relative;
}

.tnxbsv-upload .input-group-append .icon-clear {
    position: absolute;
    right: calc(100% + 0.75rem);
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    z-index: 10;
    color: var(--bs-tertiary-color);
}

.tnxbsv-upload .input-group-append .icon-clear:hover {
    color: var(--bs-secondary-color);
}

.tnxbsv-upload .input-group-append .btn {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.tnxbsv-upload-error {
    margin-top: 0.25rem;
    color: var(--bs-danger);
    font-size: 87.5%;
}

.tnxbsv-upload-placeholder {
    margin-top: 0.25rem;
    color: var(--bs-tertiary-color);
    font-size: 87.5%;
}
</style>
